<?php
/**
 * Writes object to CSV. 
 *
 * Usage: 
 * $data1 = new stdClass( );
 * $data1->song = 'The Spirit of Radio';
 * $data1->type = 'Rock';
 * $data1->band = 'Rush';
 * $data1->contributors = array();
 * $data1->contributors[] = array('name' => 'Geddy Lee', 'role'=>'Lead Vocals');
 * $data1->contributors[] = array('name' => 'Geddy Lee', 'role'=>'Bass');
 * $data1->contributors[] = array('name' => 'Alex Lifeson', 'role'=>'Guitar');
 * $data1->contributors[] = array('name' => 'Neil Peart', 'role'=>'Lyrics');
 * $data1->contributors[] = array('name' => 'Neil Peart', 'role'=>'Percussion');
 *        
 * $data2 = new stdClass( );
 * $data2->song = 'YYZ';
 * $data2->type = 'Rock';
 * $data2->band = 'Rush';
 * $data2->contributors = array();
 * $data2->contributors[] = array('name' => 'Geddy Lee', 'role'=>'Bass');
 * $data2->contributors[] = array('name' => 'Alex Lifeson', 'role'=>'Guitar');
 * $data2->contributors[] = array('name' => 'Neil Peart', 'role'=>'Percussion');
 * 
 * $list = array($data1, $data2);
 * $writer = new Rest_Util_CsvWriter();
 * echo $writer->getXML( $data );
 * 
 * CSV Result: 
 * "song","type","band","contributors1_name","contributors1_role","contributors2_name","contributors2_role","contributors3_name","contributors3_role","contributors4_name","contributors4_role","contributors5_name","contributors5_role"
 * "The Spirit of Radio","Rock","Rush","Geddy Lee","Lead Vocals","Geddy Lee","Bass","Alex Lifeson","Guitar","Neil Peart","Lyrics","Neil Peart","Percussion"
 * "YYZ","Rock","Rush","Geddy Lee","Bass","Alex Lifeson","Guitar","Neil Peart","Percussion"
 */

class Rest_Util_CsvWriter
{
    private $fieldSeperator = ',';
    private $fieldEnclosure = '"';
    private $recordSeperator = "\r\n";
    
    private $header;
    private $records;
    private $headerLabels;

    public function getCSV ( $list, $fieldSeperator=NULL, $fieldEnclosure=NULL, $recordSeparator=NULL )
    {
        if(!$this->is_array($list))
            throw new Exception('Invalid data type - expected type is array.');
        
        if($fieldSeperator)    
           $this->fieldSeperator = $fieldSeperator;

        if($fieldEnclosure)    
           $this->fieldEnclosure = $fieldEnclosure;

        if($recordSeparator)    
           $this->recordSeparator = $recordSeparator;   
        
        $this->headerLabels = array();
        $this->header = array();
        $this->records = array();
        
        $this->_createRecords( $list );
        
        foreach ($this->records as $key => $value)
        {
            $this->records[$key] = implode($this->fieldSeperator, $value);
        }

        return implode($this->fieldSeperator, $this->header) . $this->recordSeperator  . implode( $this->recordSeperator, $this->records);
    }

    private function _createRecords( $list, $label='' )
    {
        foreach ( $list as $index => $item ) {
            
            if(!$label)
                $this->records[] = array();
         
            foreach ($item as $key => $value) {
                if( is_array($value) ){
                    $this->_createRecords($value, $key, $this->records[count($this->records)-1]);
                } else {
                    $headerLabel = $label ? $label.($index+1).'_'.$key : $key ;
                    
                    if(!array_key_exists($headerLabel, $this->headerLabels))
                    {
                        $this->header[] = $this->fieldEnclosure . $headerLabel . $this->fieldEnclosure;
                        $this->headerLabels[$headerLabel] = true;
                    }
                   
                    $this->records[count($this->records)-1][] = $this->fieldEnclosure . $value . $this->fieldEnclosure;
                }
            }
            
        }
    }
    
    private function is_array ( $array )
    { 
       if ( !is_array($array) || empty($array) ) {
          return false;
       }
       $next = 0;
       foreach ( $array as $k => $v ) {
          if ( $k !== $next ) return false;
          $next++;
       }
       return true;
    }
}

?>